#!/usr/bin/python
# -*- coding:utf-8 -*-

import os
import re
import platform
import re

# 需要忽略的文件或者文件夹的名字
ignore_names = ['.git', 'index.md']
# 符合建立所以要求的文件的后缀名
ext_names = ['md', 'markdown']

def CheckIgnore(path):
    '''
    检查文件是否为应该忽略的文件
    '''
    abs_path = os.path.abspath(path)
    for n in ignore_names:
        name = os.path.split(abs_path)[1]
        if name == n:
            return True            
    return False
    
def checkExtension(name):
    '''
    检查后缀名是不是符合要求
    '''
    ext = os.path.splitext(name)[1]
    if len(ext) == 0:
        return False
    ext = ext[1:]
    for n in ext_names:
        if ext == n:
            return True
    return False

class FileNode(object):
    '''
    该类用于表示文件树节点
    注意，需要显式调用pharseDir函数才可以对文件树进行遍历
    '''
    def __init__(self, path, level = 1):
        # 相对路径
        self.path = path
        # 路径的等级
        self.level = level
        self.is_dir = os.path.isdir(path)
        self.abs_path = os.path.abspath(self.path)
        self.name = os.path.split(self.abs_path)[1]
        self.children = None
        self.child_revursive = False
        
    def getChildren(self, recursive = False):
        '''
        更新文件节点的孩子节点
        '''
        self.children = []
        self.child_revursive = recursive
        if self.isDir():
            for lists in os.listdir(self.path):
                if CheckIgnore(os.path.join(self.path, lists)):
                    continue
                child_node = FileNode(os.path.join(self.path, lists), 
                                      self.level + 1)
                if recursive:
                    child_node.getChildren(recursive)
                self.children.append(child_node)
                
        return self.children
                
    def printAll(self, abs_path = False):
        if abs_path:
            print('%s : %d' % (self.abs_path, self.level))
        else:
            print('%s : %d' % (self.path, self.level))
        for child in self.children:
            child.printAll(abs_path)
            
    def isDir(self):
        return self.is_dir
        
    def rename(self, new_name):
        old_abs_path = self.abs_path
        
        new_path = os.path.join(os.path.split(self.path)[0], new_name)
        os.rename(self.path, new_path)
        
        self.path = new_path
        self.abs_path = os.path.abspath(self.path)
        self.name = os.path.split(self.abs_path)[1]
        
        if self.children is not None:
            self.getChildren(self.child_revursive)
            
        print('WARNING: File or directory:\n%s\nhas been renamed to\n%s\n' % 
              (old_abs_path, self.abs_path))
            
class IndexWriter(object):
    '''
    该类用来按照Markdown格式向索引文件写入内容
    '''
    def __init__(self, file_name):
        self.file_name = file_name
        self.is_opened = False
        self.add_line = False
        self.openFile()
        
    def openFile(self):
        if self.is_opened is True:
            return
        if os.path.isdir(self.file_name):
            raise ValueError('%s is not a file!' % self.file_name)
        self.file_handler = open(self.file_name, 'wt')
        self.is_opened = True
        
    def closeFile(self):
        if self.is_opened is False:
            return
        self.file_handler.close()
        self.is_opened = False
        
    def writeStr(self, s):
        '''
        对文件写入的一层封装，主要为了解决编码问题
        '''
        if platform.system() == 'Windows':
            s = s.decode('gbk').encode('utf-8')
        self.file_handler.write(s)
        
    def writeTitle(self, name, level):
        '''
        写入标题
        name: 标题名字
        level: 标题等级
        '''
        if self.add_line:
            self.writeStr('\n')
            self.add_line = False
        self.writeStr('#' * level + ' ')
        self.writeStr('%s\n\n' % name)
        
    def writeItem(self, name ,path):
        '''
        写入索引内容
        name: 索引名字
        path: 索引所指向的位置
        '''
        # 适配Windows的路径分隔符
        path = self.convertPathSpliter(path)
        self.writeStr('- [%s](%s)\n' % (name, path))
        self.add_line = True
        
    def convertPathSpliter(self, path):
        '''
        这个方法是为了适配Windows使用'\'作为目录分割符而设置的
        可以将以'\'为分隔符的路径转换成以'/'为分隔符的路径
        '''
        return '/'.join(path.split(os.path.sep))
        
class IndexGenerator(object):
    '''
    该类用来生成索引，path变量为生成索引的根目录
    '''
    def __init__(self, path):
        self.path = path
        self.file_node = FileNode(self.path)
        self.file_node.getChildren(recursive = True)
        self.have_item_dict = {}
        self.index_writer = None
        
    def generate(self, index_file_name):
        '''
        生成索引文件到index_file_name所指定的文件名中
        '''
        self.index_file_name = index_file_name
        self.index_writer = IndexWriter(self.index_file_name)
        
        self.recurseGenerate(self.file_node)
        
    def recurseGenerate(self, file_node):
        '''
        递归地遍历目录，并生成索引
        '''
        if self.index_writer is None:
            raise IOError('Index Writer has not been initialized yet.')
            
        if self.checkHaveItem(file_node):
            if re.search(' ', file_node.name) is not None:
                file_node.rename(file_node.name.replace(' ', '_'))
            if file_node.isDir():
                self.index_writer.writeTitle(file_node.name, file_node.level)
                # Handle with file first
                for child in file_node.children:
                    if not child.isDir():
                        self.recurseGenerate(child)
                for child in file_node.children:
                    if child.isDir():
                        self.recurseGenerate(child)
            else:
                item_name = os.path.splitext(file_node.name)[0]
                self.index_writer.writeItem(item_name, file_node.path)
        
    def checkHaveItem(self, file_node):
        '''
        检查该路径下是否有符合要求的文件
        '''
        # Check the dict, if exists, return the dict result
        if self.have_item_dict.has_key(file_node.abs_path):
            return self.have_item_dict[file_node.abs_path]
        # Check if this file has the correct extension.
        # If have, return True
        if checkExtension(file_node.name):
            self.have_item_dict[file_node.abs_path] = True
            return True
        # Check all its child node recursivly
        for child in file_node.children:
            if self.checkHaveItem(child):
                self.have_item_dict[file_node.abs_path] = True
                return True
        # IF all the check before fails,
        # then no item is in this file node,
        # return False
        self.have_item_dict[file_node.abs_path] = False
        return False
        
def main():
    '''
    主函数
    '''
    generator = IndexGenerator('.')
    generator.generate('index.md')
        
if __name__ == '__main__':
    main()